package com.example.demo.service.impl

import com.example.demo.config.Constant
import com.example.demo.dao.*
import com.example.demo.dao.Tables.tApks
import com.example.demo.dao.Tables.tDeptVideos
import com.example.demo.dao.Tables.tDevices
import com.example.demo.dao.Tables.tFoodTypes
import com.example.demo.dao.Tables.tFoods
import com.example.demo.dao.Tables.tJzrDepts
import com.example.demo.dao.Tables.tJzrInfo
import com.example.demo.dao.Tables.tMenus
import com.example.demo.dao.Tables.tProductTypes
import com.example.demo.dao.Tables.tQuestionnaireAnswers
import com.example.demo.dao.Tables.tQuestionnaires
import com.example.demo.dao.Tables.tUsers
import com.example.demo.dbmodels.TQuestionnaire
import com.example.demo.dbmodels.TQuestionnaireAnswer
import com.example.demo.dto.*
import com.example.demo.service.WebService
import com.example.demo.utils.GmrDatabase
import com.example.demo.utils.WebDatabase
import com.example.demo.vo.*
import com.example.demo.vo.ret.PatientInfo
import com.example.demo.vo.ret.webret.UserInfo
import com.example.demo.vo.webvo.MenuVo
import com.example.demo.vo.webvo.UserVo
import me.liuwj.ktorm.dsl.*
import me.liuwj.ktorm.entity.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import java.io.File


@Service
class WebServiceImpl(
    @Autowired
    private val webDatabase: WebDatabase,
    @Autowired
    private val gmrDatabase: GmrDatabase
) : WebService {

    override fun getMenuInfo(): List<MenuVo>? {
        webDatabase.getDataBase().tMenus.toList().let {
            MenuVo().getListVo(it).let {
                val listMenuVo = mutableListOf<MenuVo>()
                it.forEach {
                    if (it.parent_id == 0) {
                        listMenuVo.add(it)
                    }
                }
                it.groupBy {
                    it.parent_id
                }.let { map ->
                    map.forEach { vaue ->
                        listMenuVo.forEach {
                            if (vaue.key == it.id) {
                                it.menuChird = vaue.value
                            }
                        }
                    }
                }
                return listMenuVo.toList()
            }
        }
    }

    override fun getUserInfo(username: String): UserVo? {
        webDatabase.getDataBase().tUsers.filter {
            it.user_name eq username
        }.firstOrNull()?.let {
            return UserVo().getVo(it)
        } ?: return null
    }

    override fun getUserInfo(id: Int): UserVo? {
        webDatabase.getDataBase().tUsers.filter {
            it.id eq id
        }.firstOrNull()?.let {
            return UserVo().getVo(it)
        } ?: return null
    }


    override fun getUpdateAvatar(image: String, userId: String): UserInfo? {
//        webDatabase.getDataBase().tUsers.filter {
//            it.USER_ID eq userId.toLong()
//        }.firstOrNull()?.let { tUser ->
//            tUser.AVATAR = image
//            tUser.flushChanges()?.let {
//                UserVo().getVo(tUser)?.username?.apply {
//                    return getUserInfo(this)
//                }
//            }
//        }
        return null
    }

    override fun getUpdatePassword(userId: String, newPassword: String): Int? {
//        webDatabase.getDataBase().tUsers.filter {
//            it.USER_ID eq userId.toLong()
//        }.firstOrNull()?.let { tUser ->
//            tUser.PASSWORD = newPassword
//            webDatabase.getDataBase().tUsers.update(tUser).let {
//                return it
//            }
//        }
        return null
    }

    override fun getUserPassword(userId: String): String? {
//        webDatabase.getDataBase().tUsers.filter {
//            it.USER_ID eq userId.toLong()
//        }.firstOrNull()?.let {
//            return it.PASSWORD
//        }
        return null
    }

    override fun getUpdateUserInfo(userDo: UserDo): UserInfo? {
//        userDo.userId.apply {
//            webDatabase.getDataBase().tUsers.filter {
//                it.USER_ID eq this.toLong()
//            }.firstOrNull()?.let { TUser ->
//                userDo.userName.apply { TUser.USERNAME = this }
//                userDo.email.apply { TUser.EMAIL = this }
//                userDo.mobile.apply { TUser.MOBILE = this }
//                userDo.sex.apply { TUser.SSEX = this }
//                userDo.description.apply { TUser.DESCRIPTION = this }
//                userDo.deptId.apply { TUser.DEPT_ID = this.toLong() }
//                TUser.flushChanges().let {
//                    if (it == 1) {
//                        userDo.userName.apply {
//                            return getUserInfoData(this)
//                        }
//                    }
//                }
//            }
//        }
        return null
    }

    override fun getPatientInfoList(patientInfoListDo: PatientInfoListDo): PatientInfo? {
        gmrDatabase.getDataBase()
            .from(TJzrInfoDao)
            .select()
            .whereWithConditions {
                patientInfoListDo.deptId?.let { deptId ->
                    it += TJzrInfoDao.DEPT_CODE eq deptId.toInt()
                }
                patientInfoListDo.bedNo?.let { bedNo ->
                    it += TJzrInfoDao.BED_NO eq bedNo
                }
                patientInfoListDo.sex?.let { sex ->
                    it += TJzrInfoDao.SEX eq sex
                }
                patientInfoListDo.name?.let { name ->
                    it += TJzrInfoDao.NAME eq name
                }
                patientInfoListDo.nursingClass?.let { nursingClass ->
                    it += TJzrInfoDao.NURSING_CLASS eq nursingClass
                }
            }.let { query ->
                val infoVoList = mutableListOf<InfoVo>()
                query.forEach {
                    infoVoList.add(InfoVo().getVo(it))
                }
                val patientInfo = PatientInfo()
                patientInfo.listInfoVo = infoVoList
                return patientInfo
            }
    }

    override fun getPatientInfo(patientId: Int): InfoVo? {
        gmrDatabase.getDataBase().tJzrInfo.filter {
            it.ID eq patientId.toLong()
        }.firstOrNull()?.let {
            InfoVo().getVo(it).let {
                return it
            }
        } ?: return null
    }

    override fun getDeptTree(): List<DeptVo>? {
        gmrDatabase.getDataBase().tJzrDepts.toList().let { list ->
            DeptVo().getListVo(list).let {
                return it
            }
        }

    }

    override fun getDeptIdsByUserId(userId: String?): String {
        return ""
    }


//    override fun getNursingclassList(): List<NursingclassVo>? {
////        jzrDatabase.getDataBase().tNursingclass.toList().let { list ->
////            NursingclassVo().getVoList(list).let {
////                return it
////            }
////        }
//        return null
//    }

    override fun addNursingclass(nursingClassDo: NursingClassDo): Int? {
//        jzrDatabase.getDataBase().tNursingclass.insert {
//            set(tNursingclass.title, nursingClassDo.title)
//            set(tNursingclass.bgcolor, nursingClassDo.bgcolor)
//            set(tNursingclass.fontcolor, nursingClassDo.fontcolor)
//        }.let {
//            return it
//        }
        return null
    }

    override fun deleteNursingclassList(nursingClassDo: NursingClassDo): Int? {
//        nursingClassDo.id?.let { id ->
//            jzrDatabase.getDataBase().tNursingclass.delete {
//                it.id eq id
//            }.let {
//                return it
//            }
//        } ?: return null
        return null
    }

    override fun deleteQuestionnaire(id: Int): Int? {
        return webDatabase.getDataBase().tQuestionnaires.find {
            it.id eq id
        }?.delete()?.let {
            webDatabase.getDataBase().tQuestionnaireAnswers.removeIf {
                it.quest_id eq id
            }
        }
    }

    override fun addQuestionnaire(addQuestionnaireDo: AddQuestionnaireDo): Int? {
        addQuestionnaireDo.let {
            val tQuestionnaire = TQuestionnaire()
            tQuestionnaire.title = addQuestionnaireDo.title
            val id = webDatabase.getDataBase().insertAndGenerateKey(TQuestionnaireDao) {
                set(it.title, addQuestionnaireDo.title)
                set(it.deptId, addQuestionnaireDo.deptId)
                set(it.deptName, addQuestionnaireDo.deptName)
            }
            id.let {
                val tAnswer1 = TQuestionnaireAnswer()
                tAnswer1.title = addQuestionnaireDo.awan1
                tAnswer1.quest_id = id.toString().toInt()
                webDatabase.getDataBase().tQuestionnaireAnswers.add(tAnswer1)

                val tAnswer2 = TQuestionnaireAnswer()
                tAnswer2.title = addQuestionnaireDo.awan2
                tAnswer2.quest_id = id.toString().toInt()
                webDatabase.getDataBase().tQuestionnaireAnswers.add(tAnswer2)

                val tAnswer3 = TQuestionnaireAnswer()
                tAnswer3.title = addQuestionnaireDo.awan3
                tAnswer3.quest_id = id.toString().toInt()
                webDatabase.getDataBase().tQuestionnaireAnswers.add(tAnswer3)

                return id.toString().toInt()
            }
        }

    }

    override fun updateQuestionnaire(addQuestionnaireDo: AddQuestionnaireDo): Int? {
        addQuestionnaireDo.id?.let { id ->
            webDatabase.getDataBase().tQuestionnaires.find {
                it.id eq id
            }?.let {
                it.title = addQuestionnaireDo.title
                it.flushChanges()
            }
            webDatabase.getDataBase().tQuestionnaireAnswers.filter {
                it.quest_id eq id
            }.toList().let {
                val answer1 = it[0]
                answer1.title = addQuestionnaireDo.awan1
                webDatabase.getDataBase().tQuestionnaireAnswers.update(answer1)
                val answer2 = it[1]
                answer2.title = addQuestionnaireDo.awan2
                webDatabase.getDataBase().tQuestionnaireAnswers.update(answer2)
                val answer3 = it[2]
                answer3.title = addQuestionnaireDo.awan3
                webDatabase.getDataBase().tQuestionnaireAnswers.update(answer3)

                return 0
            }
        }
        return null
    }

    override fun getListQuestionnaire(): List<QuestionnaireVo>? {
        webDatabase.getDataBase().tQuestionnaires.toList().let {
            return QuestionnaireVo().getListVo(it)
        }
    }

    override fun getDetailQuestionnaire(id: Int): QuestionnaireInfoVo? {
        webDatabase.getDataBase().tQuestionnaires.filter {
            it.id eq id
        }.firstOrNull()?.let {
            val questionnaireInfoVo = QuestionnaireInfoVo()
            questionnaireInfoVo.questionnaireVo = QuestionnaireVo().getVo(it)
            webDatabase.getDataBase().tQuestionnaireAnswers.filter {
                it.quest_id eq id
            }.toList().let {
                questionnaireInfoVo.listAnswerVo = AnswerVo().getListVo(it)
                return questionnaireInfoVo
            }
        }
        return null
    }

    override fun getDetailQuestionnaireList(deptId: Int): List<QuestionnaireInfoVo>? {
        webDatabase.getDataBase().tQuestionnaires.filter {
            it.deptId eq deptId
        }.toList().let {
            val questionnaireVoList = mutableListOf<QuestionnaireInfoVo>()
            QuestionnaireVo().getListVo(it).forEach { QuestionnaireVo ->
                val questionnaireInfoVo = QuestionnaireInfoVo()
                questionnaireInfoVo.questionnaireVo = QuestionnaireVo
                QuestionnaireVo.id?.let { questId ->
                    webDatabase.getDataBase().tQuestionnaireAnswers.filter {
                        it.quest_id eq questId
                    }.toList().let {
                        questionnaireInfoVo.listAnswerVo = AnswerVo().getListVo(it)
                    }
                    questionnaireVoList.add(questionnaireInfoVo)
                }
            }
            return questionnaireVoList
        }
    }

    override fun psotDetailQuestionnaireList(questionnaireDo: List<QuestionnaireDo>): Int? {
        questionnaireDo.forEach { questionnaireDo ->
            webDatabase.getDataBase().insertAndGenerateKey(TQuestionnairePostDao) {
                set(it.deptId, questionnaireDo.deptId)
                set(it.deptName, questionnaireDo.deptName)
                set(it.bedid, questionnaireDo.bedid)
                set(it.bedName, questionnaireDo.bedName)
                set(it.patientId, questionnaireDo.patientId)
                set(it.patientName, questionnaireDo.patientName)
                set(it.questionnaireId, questionnaireDo.questionnaireId)
                set(it.questionnaireTitle, questionnaireDo.questionnaireTitle)
                set(it.answerid, questionnaireDo.answerid)
                set(it.answerTitle, questionnaireDo.answerTitle)
            }
        }
        return 0
    }

    override fun addApk(file: MultipartFile, apkName: String, apkCode: String, apkType: String): ApkVo? {

        val location = System.getProperty("user.dir") + "/Resource/apk/"
        val locationFile = File(location)
        if (!locationFile.exists()) locationFile.mkdirs()
        val filePath = locationFile.path
        val fileName = file.originalFilename
        val dest = File("$filePath/$fileName")
        file.transferTo(dest)

        val downloadUrl = Constant.RESOURCE_BASEURL + "/apk/$fileName"

        webDatabase.getDataBase().insertAndGenerateKey(TApkDao) {
            set(it.apkCode, apkCode)
            set(it.apkName, apkName)
            set(it.apkType, apkType.toInt())
            set(it.apkPath, downloadUrl)
        }
        val apkVo = ApkVo()
        apkVo.apkCode = apkCode
        apkVo.apkName = apkName
        apkVo.apkType = apkType.toInt()
        apkVo.apkPath = dest.path

        return apkVo

    }

    override fun getListApk(): List<ApkVo>? {
        webDatabase.getDataBase().tApks.toList().let {
            return ApkVo().getListVo(it)
        }
    }

    override fun deleteApk(id: Int): Int? {
        webDatabase.getDataBase().tApks.removeIf {
            it.id eq id
        }.let {
            return it
        }
    }

    override fun getListFoodType(): List<FoodTypeVo> {
        webDatabase.getDataBase().tFoodTypes.toList().let {
            return FoodTypeVo().getListVo(it)
        }
    }

    override fun addFoodType(title: String): Int? {
        webDatabase.getDataBase().insertAndGenerateKey(TFoodTypeDao) {
            set(it.title, title)
        }.let {
            return it.toString().toInt()
        }
    }

    override fun deleteFoodType(id: Int): Int? {
        webDatabase.getDataBase().tFoodTypes.removeIf {
            it.id eq id
        }.let {
            return it
        }
    }

    override fun addFood(
        title: String,
        price: Int,
        Introduction: String,
        specification: String,
        foodTypeId: Int,
        file: MultipartFile
    ): Int? {

        val location = System.getProperty("user.dir") + "/Resource/images/"
        val locationFile = File(location)

        if (!locationFile.exists()) locationFile.mkdirs()
        val filePath = locationFile.path
        val fileName = file.originalFilename
        val dest = File("$filePath/$fileName")

        file.transferTo(dest)

        val imgUrl = Constant.RESOURCE_BASEURL + "/images/$fileName"

        webDatabase.getDataBase().insertAndGenerateKey(TFoodDao) {
            set(it.title, title)
            set(it.price, price.toDouble())
            set(it.Introduction, Introduction)
            set(it.specification, specification)
            set(it.foodTypeId, foodTypeId)
            set(it.url, imgUrl)
        }.let {
            return it.toString().toInt()
        }
    }

    override fun deleteFood(id: Int): Int? {
        webDatabase.getDataBase().tFoods.removeIf {
            it.id eq id
        }.let {
            return it
        }
    }

    override fun getFoodInfo(id: Int): FoodInfoVo? {
        webDatabase.getDataBase()
            .from(TFoodDao)
            .leftJoin(TFoodTypeDao, TFoodDao.foodTypeId eq TFoodTypeDao.id)
            .select()
            .where { TFoodDao.id eq id }
            .let { query ->
                var foodInfoVo: FoodInfoVo? = null
                query.forEach {
                    foodInfoVo = FoodInfoVo().getVo(it)
                }
                return foodInfoVo
            }
    }

    override fun updateFood(
        id: Int,
        title: String,
        price: Int,
        Introduction: String,
        specification: String,
        foodTypeId: Int,
        foodTypeTitle: String
    ): Int? {
        webDatabase.getDataBase().update(TFoodDao) {
            set(it.title, title)
            set(it.price, price)
            set(it.Introduction, Introduction)
            set(it.specification, specification)
            set(it.foodTypeId, foodTypeId)
            where {
                it.id eq id
            }
        }.let {
            return it
        }

    }

    override fun getFoodList(): List<FoodInfoVo>? {
        webDatabase.getDataBase()
            .from(TFoodDao)
            .leftJoin(TFoodTypeDao, TFoodDao.foodTypeId eq TFoodTypeDao.id)
            .select()
            .let {
                val listFoodInfoVo = mutableListOf<FoodInfoVo>()
                it.forEach {
                    listFoodInfoVo.add(FoodInfoVo().getVo(it))
                }
                return listFoodInfoVo
            }
    }

    override fun getFoodListByFoodTypeId(foodTypeId: Int): List<FoodInfoVo>? {
        webDatabase.getDataBase()
            .from(TFoodDao)
            .leftJoin(TFoodTypeDao, TFoodDao.foodTypeId eq TFoodTypeDao.id)
            .select()
            .where { TFoodDao.foodTypeId eq foodTypeId }
            .let {
                val listFoodInfoVo = mutableListOf<FoodInfoVo>()
                it.forEach {
                    listFoodInfoVo.add(FoodInfoVo().getVo(it))
                }
                return listFoodInfoVo
            }

    }


    override fun addProductType(title: String): Int? {
        webDatabase.getDataBase().insertAndGenerateKey(TProductTypeDao) {
            set(it.name, title)
        }.let {
            return it.toString().toInt()
        }
    }

    override fun deleteProductType(id: Int): Int? {
        webDatabase.getDataBase().tProductTypes.removeIf {
            it.id eq id
        }.let {
            return it
        }
    }

    override fun getProductTypeList(): List<ProductTypeVo>? {
        webDatabase.getDataBase().tProductTypes.toList().let {
            return ProductTypeVo().getVoList(it)
        }
    }

    override fun addProduct(
        title: String,
        price: Int,
        Introduction: String,
        specification: String,
        productTypeId: Int,
        file: MultipartFile
    ): Int? {
        val location = System.getProperty("user.dir") + "/Resource/images/"
        val locationFile = File(location)

        if (!locationFile.exists()) locationFile.mkdirs()
        val filePath = locationFile.path
        val fileName = file.originalFilename
        val dest = File("$filePath/$fileName")

        file.transferTo(dest)
        val imgUrl = Constant.RESOURCE_BASEURL + "/images/$fileName"

        webDatabase.getDataBase().insertAndGenerateKey(TProductDao) {
            set(it.title, title)
            set(it.price, price.toDouble())
            set(it.introduction, Introduction)
            set(it.productTypeId, productTypeId)
            set(it.specification, specification)
            set(it.url, imgUrl)
        }.let {
            return it.toString().toInt()
        }
    }


    override fun getProductInfoList(): List<ProductInfoVo>? {
        webDatabase.getDataBase()
            .from(TProductDao)
            .leftJoin(TProductTypeDao, TProductDao.productTypeId eq TProductTypeDao.id)
            .select()
            .let {
                val listProductInfoVo = mutableListOf<ProductInfoVo>()
                it.forEach {
                    listProductInfoVo.add(ProductInfoVo().getVo(it))
                }
                return listProductInfoVo
            }
    }

    override fun getProductInfoListById(productTypeId: Int): List<ProductInfoVo>? {
        webDatabase.getDataBase()
            .from(TProductDao)
            .leftJoin(TProductTypeDao, TProductDao.productTypeId eq TProductTypeDao.id)
            .select()
            .where { TProductDao.productTypeId eq productTypeId }
            .let {
                val listProductInfoVo = mutableListOf<ProductInfoVo>()
                it.forEach {
                    listProductInfoVo.add(ProductInfoVo().getVo(it))
                }
                return listProductInfoVo
            }

    }

    override fun getDeviceList(): List<DeviceVo> {
        webDatabase.getDataBase().tDevices.toList().let {
            return DeviceVo().getListVo(it)
        }
    }

    override fun getDevice(id: Int): DeviceVo? {
        webDatabase.getDataBase().tDevices.filter {
            it.id eq id
        }.firstOrNull()?.let {
            return DeviceVo().getVo(it)
        } ?: return null
    }

    override fun addDeptVideo(
        deptid: Int,
        deptName: String,
        videoTitle: String,
        videoImageUrl: String,
        videoUrl: String
    ): Int? {
        webDatabase.getDataBase().insertAndGenerateKey(TDeptVideoDao) {
            set(it.deptId, deptid)
            set(it.deptName, deptName)
            set(it.videoTitle, videoTitle)
            set(it.videoImageUrl, videoImageUrl)
            set(it.videoUrl, videoUrl)
        }.let {
            return it.toString().toInt()
        }
    }

    override fun deleteDeptVideo(id: Int): Int? {
        webDatabase.getDataBase().tDeptVideos.removeIf {
            it.id eq id
        }.let {
            return it
        }
    }

    override fun getDeptVideoList(deptid: Int?): List<DeptVideoVo>? {
        webDatabase.getDataBase()
            .from(TDeptVideoDao)
            .select()
            .whereWithConditions {
                deptid?.let { deptid ->
                    it += TDeptVideoDao.deptId eq deptid
                }
            }.let { query ->
                val deptVideoVoList = mutableListOf<DeptVideoVo>()
                query.forEach {
                    val deptVideoVo = DeptVideoVo()
                    deptVideoVo.id = it[TDeptVideoDao.id]
                    deptVideoVo.deptId = it[TDeptVideoDao.deptId]
                    deptVideoVo.videoTitle = it[TDeptVideoDao.videoTitle]
                    deptVideoVo.deptName = it[TDeptVideoDao.deptName]
                    deptVideoVo.videoUrl = it[TDeptVideoDao.videoUrl]
                    deptVideoVo.videoImageUrl = it[TDeptVideoDao.videoImageUrl]
                    deptVideoVoList.add(deptVideoVo)
                }
                return deptVideoVoList
            }
    }


}